import { Matrix4 } from "../utils/Matrix4";
import { Render } from "./Render";
import { IBufferInfo, WebglBase } from "./WebglBase";
/*
 * @Author: Snow
 * @Date: 2021-09-16 15:45:35
 * @Description: 
 */
export class Webgl3DBase extends WebglBase {

    public override initGLSL(): void {
        this.vsSource = `
            attribute vec4 aVertexPosition;
            uniform mat4 uViewMatrix;
            varying vec4 vColor;
            void main() {
                gl_Position = uViewMatrix * aVertexPosition;
            }
        `;

        this.fsSource = `
            varying mediump vec4 vColor;
            void main() {
                gl_FragColor = vec4(1,0,0,1);
            }
        `;
    }

    public override initUITools():void{
        const gl = Render.GL;
        let translation = [200, 150];
        let angleInRadians = 0;
        let scale = [1, 1];

        // Setup a ui.
        const webglLessonsUI = (window as any).webglLessonsUI;
        webglLessonsUI.setupSlider("#x", {value: translation[0], slide: this.onUpateSlide(this,"x"), max: gl.canvas.width });
        webglLessonsUI.setupSlider("#y", {value: translation[1], slide: this.onUpateSlide(this,"y"), max: gl.canvas.height});
        webglLessonsUI.setupSlider("#z", {value: 0, slide: this.onUpateSlide(this,"z"), max: 5, min:-5,step:0.01,precision:2});
        webglLessonsUI.setupSlider("#angle", {slide: this.onUpateSlide(this,"angle"), max: 360});
        webglLessonsUI.setupSlider("#scaleX", {value: scale[0], slide: this.onUpateSlide(this,"scaleX"), min: -5, max: 5, step: 0.01, precision: 2});
        webglLessonsUI.setupSlider("#scaleY", {value: scale[1], slide: this.onUpateSlide(this,"scaleY"), min: -5, max: 5, step: 0.01, precision: 2});
        this.createSlider("scaleZ",{value: scale[1], slide: this.onUpateSlide(this,"scaleZ"), min: -5, max: 5, step: 0.01, precision: 2})
        this.createSlider("rotationX",{value: 0, slide: this.onUpateSlide(this,"rotationX"), min: 0, max: 360, step: 1, precision: 0})
        this.createSlider("rotationY",{value: 0, slide: this.onUpateSlide(this,"rotationY"), min: 0, max: 360, step: 1, precision: 0})
        this.createSlider("rotationZ",{value: 0, slide: this.onUpateSlide(this,"rotationZ"), min: 0, max: 360, step: 1, precision: 0})

        this.uiParam = {x:0,y:0,z:0,rotationX:0,rotationY:0,rotationZ:0,scaleX:1,scaleY:1,scaleZ:1,anchorX:0,anchorY:0};
    }

    public override initBuffer(): IBufferInfo {
        const gl = Render.GL;
        const vPos = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, vPos);
        const vertices = [
            // 左竖
            0, 0, 0,
            30, 0, 0,
            0, 150, 0,
            0, 150, 0,
            30, 0, 0,
            30, 150, 0,

            // 上横
            30, 0, 0,
            100, 0, 0,
            30, 30, 0,
            30, 30, 0,
            100, 0, 0,
            100, 30, 0,

            // 中横
            30, 60, 0,
            67, 60, 0,
            30, 90, 0,
            30, 90, 0,
            67, 60, 0,
            67, 90, 0,
        ];

        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);

        //顶点
        const indexs = [
            0, 1, 2, 3, 4, 5,
            6, 7, 8, 9, 10, 11,
            12, 13, 14, 15, 16, 17
        ];

        const indexsBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexsBuffer);
        gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indexs), gl.STATIC_DRAW);

        this.bufferInfo = {vPos:vPos,vColor:null,indices:indexsBuffer};
        return this.bufferInfo;
    }

    public override draw(param?:any):void{
        const gl = Render.GL;
        gl.viewport(0, 0, gl.canvas.clientWidth, gl.canvas.clientHeight);
		gl.clearColor(1.0,1.0,1.0,1.0);
		gl.clearDepth(1.0);
		gl.enable(gl.DEPTH_TEST);
		gl.depthFunc(gl.LEQUAL);
		gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

        //this.updateMatrix();
        //上传顶点数据到shader
        {
            const numComponents = 3;  // pull out 3 values per iteration
			const type = gl.FLOAT;    // the data in the buffer is 32bit floats
			const normalize = false;  // don't normalize
			const stride = 0;         // how many bytes to get from one set of values to the next
									// 0 = use type and numComponents above
			const offset = 0;         // how many bytes inside the buffer to start from
			gl.bindBuffer(gl.ARRAY_BUFFER, this.bufferInfo.vPos);
			gl.vertexAttribPointer(
				this.programInfo.attributes.aVertexPosition,
				numComponents,
				type,
				normalize,
				stride,
				offset);
			gl.enableVertexAttribArray(
				this.programInfo.attributes.aVertexPosition);
        }
        
        ////上传顶点颜色
        // {
		// 	gl.enableVertexAttribArray(this.programInfo.attributes.aVertexColor);	
		// 	gl.bindBuffer(gl.ARRAY_BUFFER,this.bufferInfo.vColor);
		// 	gl.vertexAttribPointer(
		// 		this.programInfo.attributes.aVertexColor,
		// 		4,
		// 		gl.FLOAT,
		// 		false,
		// 		0,
        //         0);
        // }

        // Tell WebGL which indices to use to index the vertices
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.bufferInfo.indices);

        // Tell WebGL to use our program when drawing\
        gl.useProgram(this.shaderProgram);


        let x = this.uiParam["x"];
        let y = this.uiParam["y"];
        let z = this.uiParam["z"];
        let rotationX = this.uiParam["rotationX"];
        let rotationY = this.uiParam["rotationY"];
        let rotationZ = this.uiParam["rotationZ"];

        let scaleX = this.uiParam["scaleX"];
        let scaleY = this.uiParam["scaleY"];
        let scaleZ = this.uiParam["scaleZ"];

        let anchorX = this.uiParam["anchorX"];
        let anchorY = this.uiParam["anchorY"];

        let angleInRadiansX = rotationX *Math.PI / 180;

        let angleInRadiansY = rotationY *Math.PI / 180;

        let angleInRadiansZ = rotationZ *Math.PI / 180;


        let matrix:number[] = Matrix4.create();;
        
        let projectionMatrix:number[] = Matrix4.projection(gl.canvas.width,gl.canvas.height,400);
        
        let translationMatrix:number[] = Matrix4.translation(x,y,z);
        
        let rotationXMatrix:number[] = Matrix4.rotateX(angleInRadiansX);

        let rotationYMatrix:number[] = Matrix4.rotateY(angleInRadiansY);
        
        let rotationZMatrix:number[] = Matrix4.rotateZ(angleInRadiansZ);

        let scalingMatrix:number[] = Matrix4.scaling(scaleX,scaleY,scaleZ);
        

        matrix = Matrix4.multiply(matrix,projectionMatrix);
        matrix = Matrix4.multiply(matrix,translationMatrix);
        matrix = Matrix4.multiply(matrix,rotationXMatrix);
        matrix = Matrix4.multiply(matrix,rotationYMatrix);
        matrix = Matrix4.multiply(matrix,rotationZMatrix);
        matrix = Matrix4.multiply(matrix,scalingMatrix);


        gl.uniformMatrix4fv(
			this.programInfo.uniforms.uViewMatrix,
			false,
			new Float32Array(matrix));
		// gl.uniformMatrix4fv(
		// 	this.programInfo.uniforms.uModelViewMatrix,
		// 	false,
		// 	this.modelViewMatrix);
        // gl.uniformMatrix4fv(
        //         this.programInfo.uniforms.uViewMatrix,
        //         false,
        //         this.viewMatrix);
        
        gl.drawElements(gl.TRIANGLES,18,gl.UNSIGNED_SHORT,0);
    }
}